﻿using System.Collections;
using Database.Core.Exceptions;
using System.Configuration;

namespace Database.ODBC
{
  /// <summary>
  /// List of ODBC connection strings.
  /// </summary>
  public class ConnectionList
  {
    private readonly Hashtable _connections = new Hashtable();
    private string _defaultConnection = string.Empty;

    /// <summary>
    /// Gets or sets the default connection.
    /// </summary>
    /// <value>The default connection.</value>
    /// <exception cref="UnknownConnection">The default connection must already be defined within Connections. The connection ' + value + ' is unknown.</exception>
    public string DefaultConnection
    {
      get
      {
        return _defaultConnection;
      }
      set
      {
        if (!_connections.ContainsKey(value))
        {
          throw new UnknownConnection("The default connection must already be defined within Connections. The connection '" + value + "' is unknown.");
        }

        _defaultConnection = value;
      }
    }

    /// <summary>
    /// Gets or sets the <see cref="System.String"/> with the specified key.
    /// </summary>
    /// <param name="key">The key.</param>
    /// <returns>System.String.</returns>
    /// <exception cref="UnknownConnection">
    /// Unable to retrieve connection. The provided connection ' + key + ' is not a known connection.
    /// or
    /// Unable to set connection. The provided connection ' + key + ' is not a known connection.
    /// </exception>
    public string this[string key]
    {
      get
      {
        if (_connections.ContainsKey(key))
        {
          return (string)_connections[key];
        }

        throw new UnknownConnection("Unable to retrieve connection. The provided connection '" + key + "' is not a known connection.");
      }
      set
      {
        if (!_connections.ContainsKey(value))
        {
          throw new UnknownConnection("Unable to set connection. The provided connection '" + key + "' is not a known connection.");
        }

        _connections[key] = value;
      }
    }

    /// <summary>
    /// Adds the specified key.
    /// </summary>
    /// <param name="key">The key.</param>
    /// <param name="value">The value.</param>
    /// <exception cref="ConnectionAlreadyExists">The connection  + key +  already exists.</exception>
    public void Add(string key, string value)
    {
      if (_connections.ContainsKey(key))
      {
        throw new ConnectionAlreadyExists("The connection " + key + " already exists.");
      }

      _connections.Add(key, value);
    }

    /// <summary>
    /// Removes the specified key.
    /// </summary>
    /// <param name="key">The key.</param>
    public void Remove(string key)
    {
      _connections.Remove(key);
    }

    /// <summary>
    /// Loads connection strings from the configuration file.
    /// </summary>
    /// <param name="defaultConnectionName">Default connection string to use.</param>
    /// <exception cref="NoConnectionsDefined">There are no connections defined in the configuration file.</exception>
    /// <exception cref="ConnectionAlreadyExists">The connection  + key +  already exists.</exception>
    public void LoadConfigFileConnections(string defaultConnectionName = null)
    {
      var connectionStrings = ConfigurationManager.ConnectionStrings;

      if(connectionStrings == null
         || connectionStrings.Count == 0)
      {
        throw new NoConnectionsDefined("There are no connections defined in the configuration file!");
      }

      string first = null;

      foreach(ConnectionStringSettings connectionString in connectionStrings)
      {
        //Only want Odbc connection strings
        if(connectionString.ProviderName != "System.Data.Odbc")
        {
          continue;
        }

        //should only grab the first entry
        if(first == null)
        {
          first = connectionString.Name;
        }

        Add(connectionString.Name, connectionString.ConnectionString);
      }

      if(defaultConnectionName != null)
      {
        _defaultConnection = defaultConnectionName;

        return;
      }

      if(_defaultConnection == null)
      {
        _defaultConnection = first;
      }
    }
  }
}
